#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <unistd.h>

/* 游戏区域定义 */
#define ARENA_COLS 10
#define ARENA_ROWS 20
#define PIECE_VARIANTS 7
#define BUFFER_ZONE 5  // 顶部预留空间

/**
 * 方块单元坐标结构
 */
typedef struct {
    int y_pos;
    int x_pos;
} UnitCoordinate;

/**
 * 所有方块形状定义 - 每种形状有4种旋转状态
 */
UnitCoordinate all_piece_data[PIECE_VARIANTS][4][4] = {
    // I形状
    {
        {{0,0}, {0,1}, {0,2}, {0,3}},
        {{0,0}, {1,0}, {2,0}, {3,0}},
        {{0,0}, {0,1}, {0,2}, {0,3}},
        {{0,0}, {1,0}, {2,0}, {3,0}},
    },
    // O形状
    {
        {{0,0}, {1,0}, {0,1}, {1,1}},
        {{0,0}, {1,0}, {0,1}, {1,1}},
        {{0,0}, {1,0}, {0,1}, {1,1}},
        {{0,0}, {1,0}, {0,1}, {1,1}}
    },
    // T形状
    {
        {{1,0}, {0,1}, {1,1}, {1,2}},
        {{0,0}, {1,0}, {2,0}, {1,1}},
        {{1,0}, {0,1}, {1,1}, {1,2}},
        {{0,1}, {1,1}, {2,1}, {1,0}},
    },
    // Z形状
    {
        {{0,0}, {0,1}, {1,1}, {1,2}},
        {{1,0}, {2,0}, {0,1}, {1,1}},
        {{0,0}, {0,1}, {1,1}, {1,2}},
        {{1,0}, {2,0}, {0,1}, {1,1}},
    },
    // S形状
    {
        {{1,0}, {0,1}, {1,1}, {0,2}},
        {{0,0}, {1,0}, {1,1}, {2,1}},
        {{1,0}, {0,1}, {1,1}, {0,2}},
        {{0,0}, {1,0}, {1,1}, {2,1}},
    },
    // J形状
    {
        {{1,0}, {1,1}, {1,2}, {0,0}},
        {{0,0}, {0,1}, {1,0}, {2,0}},
        {{0,0}, {0,1}, {0,2}, {1,2}},
        {{0,1}, {1,1}, {2,1}, {2,0}},
    },
    // L形状
    {
        {{1,0}, {1,1}, {1,2}, {0,2}},
        {{0,0}, {1,0}, {2,0}, {2,1}},
        {{0,0}, {1,0}, {0,1}, {0,2}},
        {{0,0}, {0,1}, {1,1}, {2,1}}
    }
};

/**
 * AI评估参数 - 适当调整以降低AI强度
 */
const double ai_parameters[] = {
    -5.0,  // 高度惩罚因子 (原-4.8)
    3.0,   // 消行奖励因子 (原3.2)
    -3.5,  // 行变化惩罚因子 (原-3.3)
    -8.7,  // 列变化惩罚因子 (原-9.0)
    -7.2,  // 空洞惩罚因子 (原-7.6)
    -4.0   // 井深惩罚因子 (原-3.7)
};

/* 全局游戏状态 */
long int total_points = 0;
int current_arena[ARENA_ROWS][ARENA_COLS] = {0};
int temp_arena[ARENA_ROWS][ARENA_COLS] = {0};

/**
 * 检查指定坐标是否被占用或超出边界
 * @return 1=被占用/出界, 0=安全
 */
int is_cell_blocked(int row, int col, int arena[ARENA_ROWS][ARENA_COLS]) {
    // 检查边界
    if (col < 0 || col >= ARENA_COLS || row < 0 || row >= ARENA_ROWS-BUFFER_ZONE) {
        return 1;
    }
    
    // 检查占用
    return arena[row][col] ? 1 : 0;
}

/**
 * 检查方块在指定位置是否有碰撞
 * @return 1=可以放置, 0=不能放置
 */
int can_place_piece(int piece_type, int rotation, int base_row, int base_col) {
    UnitCoordinate *piece_units = all_piece_data[piece_type][rotation];
    
    for (int i = 0; i < 4; i++) {
        int check_row = base_row + piece_units[i].y_pos;
        int check_col = base_col + piece_units[i].x_pos;
        
        if (is_cell_blocked(check_row, check_col, current_arena)) {
            return 0;
        }
    }
    
    return 1;
}

/**
 * 计算方块可以放置的最低位置
 * @return 最低行位置, 如无法放置则返回-1
 */
int compute_drop_position(int piece_type, int rotation, int base_col) {
    int drop_row = -1;
    
    // 从顶部开始逐行尝试
    for (int test_row = 0; test_row <= ARENA_ROWS-BUFFER_ZONE-1; test_row++) {
        if (can_place_piece(piece_type, rotation, test_row, base_col)) {
            drop_row = test_row;
        } else {
            break; // 一旦不能放置就停止
        }
    }
    
    return drop_row;
}

/**
 * 将方块形状应用到游戏区域
 * 使用矩阵转换方式放置方块
 */
void apply_piece_to_arena(int piece_type, int rotation, int base_row, int base_col, 
                         int arena[ARENA_ROWS][ARENA_COLS]) {
    // 获取当前方块形状
    UnitCoordinate *piece_shape = all_piece_data[piece_type][rotation];
    int matrix[4][2];
    
    // 构建目标坐标数组
    for (int i = 0; i < 4; i++) {
        matrix[i][0] = base_row + piece_shape[i].y_pos;  // 行坐标
        matrix[i][1] = base_col + piece_shape[i].x_pos;  // 列坐标
    }
    
    // 遍历坐标数组并填充有效位置
    for (int j = 0; j < 4; j++) {
        int row = matrix[j][0];
        int col = matrix[j][1];
        
        // 检查坐标是否在有效范围内
        if (row >= 0 && col >= 0 && 
            row < ARENA_ROWS-BUFFER_ZONE && 
            col < ARENA_COLS) {
            // 使用掩码设置对应位置
            arena[row][col] |= 1;
        }
    }
}

/**
 * 检查行是否已填满
 */
int is_line_complete(int arena[ARENA_ROWS][ARENA_COLS], int row) {
    for (int col = 0; col < ARENA_COLS; col++) {
        if (!arena[row][col]) return 0;
    }
    return 1;
}

/**
 * 将指定行以上所有行下移一行
 */
void collapse_line(int arena[ARENA_ROWS][ARENA_COLS], int target_row) {
    for (int row = target_row; row > 0; row--) {
        memcpy(arena[row], arena[row-1], ARENA_COLS * sizeof(int));
    }
    memset(arena[0], 0, ARENA_COLS * sizeof(int));
}

/**
 * 重新实现清除完整行的函数
 * 使用状态机方式处理行消除
 */
int process_completed_lines(int arena[ARENA_ROWS][ARENA_COLS]) {
    int removed_lines = 0;
    int processing_state = 0; // 0=扫描中, 1=已找到满行
    
    // 从底部向上逐行扫描
    for (int row_idx = ARENA_ROWS-BUFFER_ZONE-1; row_idx >= 0;) {
        switch (processing_state) {
            case 0: // 扫描状态
                // 检查当前行是否已满
                int filled_cells = 0;
                for (int col_idx = 0; col_idx < ARENA_COLS; col_idx++) {
                    if (arena[row_idx][col_idx]) {
                        filled_cells++;
                    }
                }
                
                if (filled_cells == ARENA_COLS) {
                    // 行已满，切换到消除状态
                    processing_state = 1;
                } else {
                    // 行未满，继续向上扫描
                    row_idx--;
                }
                break;
                
            case 1: // 消除状态
                // 消除当前行并计数
                removed_lines++;
                
                // 下移上方所有行
                for (int move_row = row_idx; move_row > 0; move_row--) {
                    // 逐列复制上一行的内容
                    for (int col_idx = 0; col_idx < ARENA_COLS; col_idx++) {
                        arena[move_row][col_idx] = arena[move_row-1][col_idx];
                    }
                }
                
                // 清空最顶行
                for (int col_idx = 0; col_idx < ARENA_COLS; col_idx++) {
                    arena[0][col_idx] = 0;
                }
                
                // 回到扫描状态，但不改变当前行索引(因为需要重新检查该行)
                processing_state = 0;
                break;
        }
    }
    
    return removed_lines;
}

/**
 * 更新游戏得分
 * @return 本次得分
 */
int add_points_for_lines(int line_count) {
    int points_for_lines[] = {0, 100, 300, 500, 800};
    int earned = points_for_lines[line_count];
    total_points += earned;
    return earned;
}

/**
 * 寻找井结构并计算其价值
 * 井是指两侧有方块的空列
 */
int evaluate_wells(int arena[ARENA_ROWS][ARENA_COLS]) {
    int total_well_value = 0;
    
    for (int col = 0; col < ARENA_COLS; col++) {
        for (int row = ARENA_ROWS-BUFFER_ZONE-1; row >= 0; row--) {
            // 跳过已占用的单元格
            if (arena[row][col]) continue;
            
            // 检查左右两侧是否有方块
            int left_has_block = (col == 0) ? 1 : arena[row][col-1];
            int right_has_block = (col == ARENA_COLS-1) ? 1 : arena[row][col+1];
            
            // 如果两侧都有方块，则计算井的深度
            if (left_has_block && right_has_block) {
                int depth = 0;
                
                for (int r = row; r >= 0; r--) {
                    // 井深度累加条件
                    if (!arena[r][col] && 
                        (col == 0 || arena[r][col-1]) && 
                        (col == ARENA_COLS-1 || arena[r][col+1])) {
                        depth++;
                    } else {
                        break;
                    }
                }
                
                // 计算井价值 (1+2+...+depth)
                int well_value = 0;
                for (int i = 1; i <= depth; i++) {
                    well_value += i;
                }
                
                total_well_value += well_value;
                row -= (depth - 1); // 跳过已计算的井部分
            }
        }
    }
    
    return total_well_value;
}

/**
 * 计算方块最高点
 */
int get_max_height(int piece_type, int rotation, int base_row) {
    UnitCoordinate *units = all_piece_data[piece_type][rotation];
    int max_height = 0;
    
    for (int i = 0; i < 4; i++) {
        int unit_height = base_row + units[i].y_pos;
        if (unit_height > max_height) {
            max_height = unit_height;
        }
    }
    
    return max_height;
}

/**
 * 计算水平和垂直变化的统一函数
 * @param is_horizontal 1表示计算水平变化，0表示计算垂直变化
 */
int count_transitions(int arena[ARENA_ROWS][ARENA_COLS], int is_horizontal) {
    int changes = 0;
    
    if (is_horizontal) {
        // 计算水平变化 - 行优先遍历
        for (int row = 0; row < ARENA_ROWS-BUFFER_ZONE; row++) {
            // 假设边界是实心的
            int border_state = 1;
            int previous = border_state;
            
            for (int col = 0; col < ARENA_COLS; col++) {
                int current = arena[row][col];
                
                // 状态变化时增加计数
                changes += (previous != current) ? 1 : 0;
                previous = current;
            }
            
            // 检查右边界变化
            changes += (previous != border_state) ? 1 : 0;
        }
    } else {
        // 计算垂直变化 - 列优先遍历
        for (int col = 0; col < ARENA_COLS; col++) {
            // 假设边界是实心的
            int border_state = 1;
            int previous = border_state;
            
            for (int row = 0; row < ARENA_ROWS-BUFFER_ZONE; row++) {
                int current = arena[row][col];
                
                // 状态变化时增加计数
                changes += (previous != current) ? 1 : 0;
                previous = current;
            }
            
            // 检查底部边界变化
            changes += (previous != border_state) ? 1 : 0;
        }
    }
    
    return changes;
}

/**
 * 使用统一的变化计数函数
 */
int count_horizontal_transitions(int arena[ARENA_ROWS][ARENA_COLS]) {
    return count_transitions(arena, 1);
}

/**
 * 使用统一的变化计数函数
 */
int count_vertical_transitions(int arena[ARENA_ROWS][ARENA_COLS]) {
    return count_transitions(arena, 0);
}

/**
 * 计算空洞数量 - 上方有方块，自身为空的单元格
 */
int count_hole_cells(int arena[ARENA_ROWS][ARENA_COLS]) {
    int hole_count = 0;
    
    for (int col = 0; col < ARENA_COLS; col++) {
        int has_block_above = 0;
        
        for (int row = 0; row < ARENA_ROWS-BUFFER_ZONE; row++) {
            if (arena[row][col]) {
                has_block_above = 1;
            } else if (has_block_above) {
                hole_count++;
            }
        }
    }
    
    return hole_count;
}

/**
 * 为候选位置评分
 */
double score_board_position(int piece_type, int rotation, int base_row, int base_col) {
    // 复制当前场地进行模拟
    memcpy(temp_arena, current_arena, sizeof(current_arena));
    
    // 模拟放置方块
    apply_piece_to_arena(piece_type, rotation, base_row, base_col, temp_arena);
    
    // 模拟消行并获取消行数
    int lines_cleared = process_completed_lines(temp_arena);
    
    // 计算各评估指标
    double landing_metric = ARENA_ROWS-BUFFER_ZONE - 
                          (base_row + get_max_height(piece_type, rotation, base_row)) / 2.0;
    int horizontal_transitions = count_horizontal_transitions(temp_arena);
    int vertical_transitions = count_vertical_transitions(temp_arena);
    int holes = count_hole_cells(temp_arena);
    int wells = evaluate_wells(temp_arena);
    
    // 根据加权系数计算总分
    return ai_parameters[0] * landing_metric +
           ai_parameters[1] * lines_cleared +
           ai_parameters[2] * horizontal_transitions +
           ai_parameters[3] * vertical_transitions +
           ai_parameters[4] * holes +
           ai_parameters[5] * wells;
}

/**
 * 计算某方块类型的横向边界，用于确定可放置范围
 */
void get_piece_width_bounds(int piece_type, int rotation, int *min_width, int *max_width) {
    *min_width = 0;
    *max_width = 0;
    
    UnitCoordinate *units = all_piece_data[piece_type][rotation];
    
    for (int i = 0; i < 4; i++) {
        if (units[i].x_pos < *min_width) *min_width = units[i].x_pos;
        if (units[i].x_pos > *max_width) *max_width = units[i].x_pos;
    }
}

/**
 * 计算最优落子位置的新实现方法
 * 使用评分比较策略确定最佳位置
 */
void find_best_position(int piece_type, int *best_rotation, int *best_col) {
    double max_score = -INFINITY;
    int max_rot = 0, max_col = 0;
    
    // 按旋转和列索引扫描所有可能位置
    for (int rot = 0; rot < 4; rot++) {
        // 获取当前旋转状态下的边界
        int left_edge = 0, right_edge = 0;
        get_piece_width_bounds(piece_type, rot, &left_edge, &right_edge);
        
        // 确定合法的列范围
        int start_col = 0 - left_edge;
        int end_col = (ARENA_COLS - 1) - right_edge;
        
        // 遍历所有可能的列位置
        for (int col_pos = start_col; col_pos <= end_col; col_pos++) {
            // 找出对应的落点行
            int drop_pos = compute_drop_position(piece_type, rot, col_pos);
            
            // 跳过无效位置
            if (drop_pos < 0) {
                continue;
            }
            
            // 计算当前位置的评分
            double cur_score = score_board_position(piece_type, rot, drop_pos, col_pos);
            
            // 调试输出 (可以根据需要启用)
            // printf("评分: 旋转=%d, 列=%d, 分数=%.2f\n", rot, col_pos, cur_score);
            
            // 只保存最高分
            if (cur_score > max_score) {
                max_score = cur_score;
                max_rot = rot;
                max_col = col_pos;
            }
            
            // 如果分数相同，优先选择靠近中间的位置（可选策略）
            else if (fabs(cur_score - max_score) < 0.001) { 
                int curr_distance = abs(col_pos - ARENA_COLS/2);
                int best_distance = abs(max_col - ARENA_COLS/2);
                
                if (curr_distance < best_distance) {
                    max_rot = rot;
                    max_col = col_pos;
                }
            }
        }
    }
    
    // 返回最佳结果
    *best_rotation = max_rot;
    *best_col = max_col;
}

/**
 * 根据字符确定方块类型
 */
int convert_char_to_piece_type(char piece_char) {
    int piece_type = -1;
    
    switch (piece_char) {
        case 'I': piece_type = 0; break;
        case 'O': piece_type = 1; break;
        case 'T': piece_type = 2; break;
        case 'Z': piece_type = 3; break;
        case 'S': piece_type = 4; break;
        case 'J': piece_type = 5; break;
        case 'L': piece_type = 6; break;
    }
    
    return piece_type;
}

/**
 * 读取单个字符并忽略部分特殊字符
 * @return 1成功，0失败
 */
int read_single_char(char* input_char) {
    int result;
    int ch;
    
    // 读取下一个非空白字符
    do {
        result = scanf("%c", &ch);
        if (result != 1) return 0;
        
        // 跳过空白字符
        if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') {
            continue;
        }
        
        *input_char = (char)ch;
        return 1;
    } while (1);
}

/**
 * 读取初始输入，更健壮的实现
 * @return 1成功，0失败
 */
int read_first_two_chars(char* first_char, char* second_char) {
    // 清空输入缓冲区
    fflush(stdin);
    
    // 读取第一个字符
    if (!read_single_char(first_char)) {
        return 0;
    }
    
    // 读取第二个字符
    if (!read_single_char(second_char)) {
        return 0;
    }
    
    return 1;
}

/**
 * 确保输出缓冲区完全刷新
 */
void send_decision_output(int column, int rotation) {
    // 确保列值在0-9范围内
    int col_output = column % 10;
    // 确保旋转值是合法的
    int rot_output = rotation % 4;
    
    // 输出决策
    printf("%d %d\n", rot_output, col_output);
    printf("%ld\n", total_points);
    
    // 强制刷新输出缓冲区
    fflush(stdout);
}

/**
 * 重新实现主游戏循环，增强错误处理
 */
int main() {
    // --- 初始化阶段 ---
    enum GameState {
        INIT,           // 初始化游戏
        READ_INITIAL,   // 读取初始方块
        PLAN_MOVE,      // 规划移动
        EXECUTE_MOVE,   // 执行移动
        HANDLE_SCORE,   // 处理得分
        PREPARE_NEXT,   // 准备下一个方块
        GAME_OVER       // 游戏结束
    };
    
    enum GameState current_state = INIT;
    int piece_type = -1;
    int best_rot = 0, best_col = 0, landing_row = -1;
    char current_char = 0, next_char = 0;
    total_points = 0;
    
    // 游戏主状态机
    while (current_state != GAME_OVER) {
        switch (current_state) {
            case INIT:
                // 初始化游戏区域
                memset(current_arena, 0, sizeof(current_arena));
                memset(temp_arena, 0, sizeof(temp_arena));
                current_state = READ_INITIAL;
                break;
                
            case READ_INITIAL:
                // 读取初始方块类型
                if (!read_first_two_chars(&current_char, &next_char)) {
                    current_state = GAME_OVER;
                    break;
                }
                
                // 错误检查 - 确保读取到有效字符
                if (convert_char_to_piece_type(current_char) < 0 ||
                    (convert_char_to_piece_type(next_char) < 0 && next_char != 'X' && next_char != 'E')) {
                    // 尝试重新读取
                    if (!read_first_two_chars(&current_char, &next_char)) {
                        current_state = GAME_OVER;
                        break;
                    }
                }
                
                current_state = PLAN_MOVE;
                break;
                
            case PLAN_MOVE:
                // 解析方块类型
                piece_type = convert_char_to_piece_type(current_char);
                if (piece_type < 0) {
                    // 无效方块类型，结束游戏
                    current_state = GAME_OVER;
                    break;
                }
                
                // 规划最佳移动
                find_best_position(piece_type, &best_rot, &best_col);
                
                // 找到落点高度
                landing_row = compute_drop_position(piece_type, best_rot, best_col);
                if (landing_row < 0) {
                    // 无法放置，使用默认值
                    best_rot = 0;
                    best_col = ARENA_COLS / 2;
                    landing_row = 0;
                }
                
                current_state = EXECUTE_MOVE;
                break;
                
            case EXECUTE_MOVE:
                // 执行方块放置
                apply_piece_to_arena(piece_type, best_rot, landing_row, best_col, current_arena);
                current_state = HANDLE_SCORE;
                break;
                
            case HANDLE_SCORE:
                {
                    // 处理消行和得分
                    int removed = process_completed_lines(current_arena);
                    add_points_for_lines(removed);
                    
                    // 输出决策结果
                    send_decision_output(best_col, best_rot);
                    current_state = PREPARE_NEXT;
                }
                break;
                
            case PREPARE_NEXT:
                // 准备下一个方块
                current_char = next_char;
                
                // 检查终止条件
                if (current_char == 'X' || current_char == 'E') {
                    current_state = GAME_OVER;
                    break;
                }
                
                // 读取换行符(如果存在)
                {
                    int ch;
                    while ((ch = getchar()) != EOF) {
                        if (ch != '\n' && ch != '\r' && ch != ' ' && ch != '\t') {
                            // 如果读取到非空白字符，则这可能是下一个方块
                            next_char = (char)ch;
                            current_state = PLAN_MOVE;
                            break;
                        }
                    }
                    
                    // 如果从上面的循环正常退出（没有break），则还需要读取下一个方块
                    if (current_state != PLAN_MOVE) {
                        if (!read_single_char(&next_char)) {
                            current_state = GAME_OVER;
                            break;
                        }
                        
                        if (next_char == 'X' || next_char == 'E') {
                            current_state = GAME_OVER;
                            break;
                        }
                        
                        current_state = PLAN_MOVE;
                    }
                }
                break;
                
            case GAME_OVER:
                // 已由循环条件处理
                break;
                
            default:
                // 未知状态，重置到初始状态
                current_state = INIT;
                break;
        }
    }
    
    // 确保最后的输出被刷新
    fflush(stdout);
    return 0;
}
